# 这可以实现c++ 和 cu 的混合编译，你只需要更改这里 linux
# DEBUG： 						是否开启debug 1, 0
# SHOW_WARNING:					是否显示warning 1, 0
# stdcpp： 						设置编译标准 c++11, c++14, c++17
# cc、nvcc： 					设置编译器 c++ 和 cuda
# exec_name:				   可执行文件名
# include_paths、library_paths、ld_librarys_names 头文件路径、库路径、库名字、多个路径和名字使用空格分割
# build_dir ： 					编译生成的内容都会放到这个文件夹里
# lib_name						库名字
DEBUG                   := 1
SHOW_WARNING            := 0
stdcpp    				:= c++17
cc        				:= g++
nvcc 					:= nvcc
exec_name 	 			:= exec
include_paths 			:= include /usr/include /usr/local/cuda/include\
						   /mnt/jft/linuxFiles/beifen/TensorRT-10.8.0.43/include\
						   /mnt/jft/linuxFiles/beifen/opencv490/include/opencv4
library_paths 			:= /usr/local/cuda/lib64 /mnt/jft/linuxFiles/beifen/TensorRT-10.8.0.43/lib\
						   /mnt/jft/linuxFiles/beifen/opencv490/lib /usr/local/cuda-11.8/lib64/stubs
ld_librarys_names 		:= cudart cublas cuda nvinfer nvonnxparser stdc++fs\
						   opencv_core opencv_imgproc opencv_highgui opencv_imgcodecs
build_dir			    := build
lib_name				:= your_lib_name

# 1. 查找文件
cpp_src_path := $(shell find src -name '*.cpp')  # 后缀名.cpp文件路径
cpp_objs_path := $(patsubst src/%.cpp, $(build_dir)/objs/%.o, $(cpp_src_path))  # .cpp文件路径替换成后缀名.o文件路径
 
cu_src_path := $(shell find src -name '*.cu')  # 后缀名.cpp文件路径
cu_objs_path := $(patsubst src/%.cu, $(build_dir)/objs/%.o, $(cu_src_path))  # .cpp文件路径替换成后缀名.o文件路径

all_objs_path := $(cpp_objs_path) $(cu_objs_path)  # 所有的objs 路径
all_objs_path := $(filter-out $(build_dir)/objs/main.o, $(all_objs_path))

# 2. 定义编译选项
include_paths := $(include_paths)        # 头文件路径
library_paths := $(library_paths)                   # 库路径
ld_librarys_names := $(ld_librarys_names)                # 库的名字
 
 
# 把每一个头文件路径前面增加-I，库文件路径前面增加-L,链接选项前面加-l
I_options := $(include_paths:%=-I%) # 头文件 编译选项
l_options := $(ld_librarys_names:%=-l%) # 库名 链接选项
L_options := $(library_paths:%=-L%) # 库路径 链接选项
r_options := $(library_paths:%=-Wl,-rpath=%) 	 # 动态库 链接选项
 
# 编译设置
linking_options 	:= $(l_options) $(L_options) $(r_options)            # 链接选项
cpp_compile_options      :=  -std=$(stdcpp) -pthread -fPIC $(I_options)  # cpp 编译选项
cu_compile_options 	     :=  --shared -Xcompiler -fPIC $(I_options)                 # cuda 编译选项,
 
ifeq ($(DEBUG),1)
cu_compile_options     +=  -g -O0 -G
cpp_compile_options      +=  -g -O0
else
cu_compile_options     +=  -O3
cpp_compile_options      +=  -O3
endif
 
ifeq ($(SHOW_WARNING),1)
cu_compile_options     +=  -Wall -Wunused-function -Wunused-variable -Wfatal-errors
cpp_compile_options      +=  -Wall -Wunused-function -Wunused-variable -Wfatal-errors
else
cu_compile_options     +=  -w
cpp_compile_options      +=  -w
endif
 
 
# 3. 编译
#定义objs下的o文件，依赖src下对应的cpp文件
# $@ = 左边的生成项
# $< = 右边的依赖项第一个
# $^ = 右边的所有依赖项
$(build_dir)/objs/%.o : src/%.cpp
	@echo "[INFO] Compiling $< to $@"
	@mkdir -p $(dir $@)
	@cc -c $^ -o $@ $(cpp_compile_options)  	# 编译
 
# CUDA 编译
$(build_dir)/objs/%.o : src/%.cu
	@echo "[INFO] Compiling $< to $@"
	@mkdir -p $(dir $@)
	@$(nvcc) -c $^ -o $@ $(cu_compile_options)
 
 
# 链接文件  to exec
$(build_dir)/workspace/$(exec_name) : $(cpp_objs_path) $(cu_objs_path)
	@echo "[INFO] Linking $@...."
	@mkdir -p $(dir $@)
	@$(cc) $^ -o $@ $(linking_options)
	@echo "[INFO] Compiling $@ Done!"
 
 
# ---------------------------------------------------------------------------------
 
# 编译成可执行文件exec,编译，不运行
compile : $(build_dir)/workspace/$(exec_name)
 
 
# 运行 依赖 编译完成
run : $(build_dir)/workspace/$(exec_name)
	@echo "[RUN] $< 👇"
	@cd $(build_dir)/workspace && ./$(exec_name) # 进入目录，执行


# ---------------------------------------------------------------------------------
# 静态库
$(build_dir)/bin/lib$(lib_name).a : $(all_objs_path)
	@echo "[INFO] Creating static library $@..."
	@mkdir -p $(dir $@)
	@ar rcs $@ $^
	@echo "[INFO] Static library created!"

# 动态库
$(build_dir)/bin/lib$(lib_name).so : $(all_objs_path)
	@echo "[INFO] Creating shared library $@..."
	@mkdir -p $(dir $@)
	@$(cc) -shared -o $@ $^ $(linking_options)
	@echo "[INFO] Shared library created!"

# 静态库目标
generate_static_lib : $(build_dir)/bin/lib$(lib_name).a
get_a : generate_static_lib
# 动态库目标
generate_shared_lib : $(build_dir)/bin/lib$(lib_name).so
get_so : generate_shared_lib
# ---------------------------------------------------------------------------------

 
debug :
	@echo $(linking_options)

clean :
	@rm -rf build


 
.PHONY : debug clean run compile generate_static_lib generate_shared_lib get_a get_so